/*
 * @Descripttion: 模拟微信服务器推送消息时间，主要应用于单元测试里
 * @version: 1.0
 * @Author: 自由如风
 * @Date: 2021-04-13 19:00:05
 * @LastEditors: 自由如风
 * @LastEditTime: 2021-05-16 15:44:15
 */
import _axios from 'axios'
import { AxiosInstance, AxiosRequestConfig } from 'axios'

import { Any as PushAny, Text, Image, Voice, Video, ShortVideo, Location, Link, MsgTypes } from '../lib/wxRequest'
import { toXML } from './parser'


export enum CutInType {
    /** 可以认证成功的请求参数 */
    usableParams = '/?signature=f43587d7f5a37254502b642491db6c18f54458dd&echostr=1498141000469575451&timestamp=1617360658&nonce=1743689942',
    /** 不能认证成功的请求参数 */
    disabledParams = '/?signature=43587d7f5a37254502b642491db6c18f54458dd&echostr=1498141000469575451&timestamp=1617360658&nonce=1743689942'
}
/**
 * 模拟微信服务器向自己发送请求（单元测试时使用）
 */
export class Imitate {
    axios: AxiosInstance
    constructor({ ...args }: AxiosRequestConfig) {
        this.axios = _axios.create({
            // 默认的请求头
            headers: {
                'user-agent': 'Mozilla/4.0',
                accept: '*/*',
                'Content-Type': 'text/xml',
                pragma: 'no-cache',
                connection: 'Keep-Alive',
            },
            ...args
        })
    }

    async cutIn(url: string = CutInType.usableParams || CutInType.disabledParams) {
        return this.axios.get(url)
    }

    /**
     * 模拟 微信服务器发送请求
     * @param params 需要发送的内容，满足Push接口要求
     * @returns 
     */
    async send(params: PushAny): Promise<any> {
        return this.axios.post('', toXML(params).toString()).catch(e => {
            console.log(e.message)
        })
    }

    async sendText(text: Text) {
        return this.send(<Text>{
            ToUserName: text.ToUserName ?? 'ToUserName',
            FromUserName: text.FromUserName ?? 'FromUserName',
            MsgType: 'text',
            CreateTime: Date.now().toString(),
            MsgId: text?.MsgId ?? 'MsgId',
            Content: text?.Content ?? 'Content',
        })
    }

    async sendImage(image: Image) {
        return this.send(<Image>{
            ToUserName: image.ToUserName ?? 'ToUserName',
            FromUserName: image.FromUserName ?? 'FromUserName',
            MsgType: 'image',
            CreateTime: Date.now().toString(),
            MsgId: image.MsgId ?? 'MsgId',
            PicUrl: image.PicUrl ?? 'PicUrl',
            MediaId: image.MediaId ?? 'MediaId'
        })
    }

    async sendVoice(voice: Voice) {
        return this.send(<Voice>{
            ToUserName: voice.ToUserName ?? 'ToUserName',
            FromUserName: voice.FromUserName ?? 'FromUserName',
            MsgType: 'voice',
            CreateTime: Date.now().toString(),
            MsgId: voice.MsgId ?? 'MsgId',
            Format: voice.Format ?? 'Format',
            Recognition: voice.Recognition ?? 'Recognition',
            MediaId: voice.MediaId ?? 'MediaId'
        })
    }

    async sendVideo(video: Video) {
        return this.send(<Video>{
            ToUserName: video.ToUserName ?? 'ToUserName',
            FromUserName: video.FromUserName ?? 'FromUserName',
            MsgType: 'video',
            CreateTime: Date.now().toString(),
            MsgId: video.MsgId ?? 'MsgId',
            ThumbMediaId: video.ThumbMediaId ?? 'ThumbMediaId',
            MediaId: video.MediaId ?? 'MediaId'
        })
    }

    async sendShortVideo(shortvideo: ShortVideo) {
        return this.send(<ShortVideo>{
            ToUserName: shortvideo.ToUserName ?? 'ToUserName',
            FromUserName: shortvideo.FromUserName ?? 'FromUserName',
            MsgType: 'shortvideo',
            CreateTime: Date.now().toString(),
            MsgId: shortvideo.MsgId ?? 'MsgId',
            ThumbMediaId: shortvideo.ThumbMediaId ?? 'ThumbMediaId',
            MediaId: shortvideo.MediaId ?? 'MediaId'
        })
    }

    async sendLocation(location: Location) {
        return this.send(<Location>{
            ToUserName: location.ToUserName ?? 'ToUserName',
            FromUserName: location.FromUserName ?? 'FromUserName',
            MsgType: 'location',
            CreateTime: Date.now().toString(),
            MsgId: location.MsgId ?? 'MsgId',
            Location_X: location.Location_X ?? 'Location_X',
            Location_Y: location.Location_Y ?? 'Location_Y',
            Scale: location.Scale ?? 'Scale',
            Label: location.Label ?? 'Label',
        })
    }
    async sendlink(link: Link) {
        return this.send(<Link>{
            ToUserName: link.ToUserName ?? 'ToUserName',
            FromUserName: link.FromUserName ?? 'FromUserName',
            MsgType: 'link',
            CreateTime: Date.now().toString(),
            MsgId: link.MsgId ?? 'MsgId',
            Title: link.Title ?? 'Title',
            Description: link.Description ?? 'Title',
            Url: link.Url ?? 'Title',
        })
    }
}

